#include "stdafx.h"
#include "ShaftScore.h"

// constructs a new ShaftScore 'object'
ShaftScore* shaftScoreConstruct(Shaft *shaft)
{
	ShaftScore *score = (ShaftScore *) malloc(sizeof(ShaftScore));
	
	score->shaft = shaft;
	score->grade = 0;

	return score;
}

// deconstruct an existing ShaftScore object
void shaftScoreDeconstruct(ShaftScore *score)
{
	free(score);
}

// grades a certain shaft by some differences in floors
ShaftScore* gradeByFloorDifferences(ShaftScore *score, int goalFloor, int currentPassengerFloor)
{
	Shaft *shaft = score->shaft;
	int currentElevatorFloor = shaft->elevator->currentFloor;

	// the lower the difference, the better
	int elevatorDifferenceScore = goalFloor - currentElevatorFloor;
	
	// be generous here, saves a lot of time if that elevator doesn't have to travel a lot
	if (currentElevatorFloor == currentPassengerFloor)
		score->grade += 5;
	else if (currentElevatorFloor > currentPassengerFloor)
		score->grade -= 2 * (currentElevatorFloor - currentPassengerFloor);
	else if (currentElevatorFloor < currentPassengerFloor)
		score->grade -= 2 * (currentPassengerFloor - currentElevatorFloor);

	return score;
}

// grades a certain shaft by the number of destinations it already has
ShaftScore* gradeByDestinations(ShaftScore *score)
{
	Shaft *shaft = score->shaft;

	if (score->shaft->elevator->destinations == NULL)
		return score;

	int destinations = shaft->elevator->destinations->count;

	// for each destination that it already has, subtract 2 scorepoints
	score->grade -= 2 * destinations;

	return score;
}

// grades an elevator by its status
// idle of course being the prevalent and most highly scored one
ShaftScore* gradeByElevatorStatus(ShaftScore *score)
{
	Shaft *shaft = score->shaft;

	switch (shaft->elevator->status)
	{
		case idle:
			score->grade += 5;
			break;

		case doorClosed:
			score->grade += 3;
			break;

		case doorOpen:
			score->grade += 1;
			break;
		
		case moving:
			score->grade += 2;
			break;
	}

	return score;
}

// the publicly available method to grade an entire shaft in one go
ShaftScore* shaftScoreGradeShaft(ShaftScore *score, int goalFloor, int currentPassengerFloor)
{
	score = gradeByDestinations(score);
	score = gradeByElevatorStatus(score);
	score = gradeByFloorDifferences(score, goalFloor, currentPassengerFloor);

	return score;
}